//
// Copyright (c) ZeroC, Inc. All rights reserved.
//

#include <Ice/Ice.h>
#include <TestI.h>

using namespace Test;
using namespace IceUtil;
using namespace Ice;
using namespace std;

InitialI::InitialI()
{
}

void
InitialI::shutdown(const Current& current)
{
    current.adapter->getCommunicator()->shutdown();
}

Test::Initial::PingPongMarshaledResult
InitialI::pingPong(shared_ptr<Value> obj, const Current& current)
{
    return PingPongMarshaledResult(obj, current);
}

void
InitialI::opOptionalException(Optional<Int> a,
                              Optional<string> b,
                              Optional<VarStruct> vs,
                              const Ice::Current&)
{
    OptionalException ex;
    ex.a = a;
    ex.b = b;
    ex.vs = vs;
    throw ex;
}

void
InitialI::opDerivedException(Optional<Int> a,
                             Optional<string> b,
                             Optional<VarStruct> vs,
                             const Ice::Current&)
{
    DerivedException ex;
    ex.a = a;
    ex.b = b;
    ex.vs = vs;
    ex.ss = b;
    ex.vs2 = vs;
    throw ex;
}

void
InitialI::opRequiredException(Optional<Int> a,
                              Optional<string> b,
                              Optional<VarStruct> vs,
                              const Ice::Current&)
{
    RequiredException ex;
    ex.a = a;
    ex.b = b;
    ex.vs = vs;
    if(b)
    {
        ex.ss = b.value();
    }
    if(vs)
    {
        ex.vs2 = vs.value();
    }
    throw ex;
}

Optional<Ice::Byte>
InitialI::opByte(Optional<Ice::Byte> p1, Optional<Ice::Byte>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<bool>
InitialI::opBool(Optional<bool> p1, Optional<bool>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Short>
InitialI::opShort(Optional<Short> p1, Optional<Short>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Int>
InitialI::opInt(Optional<Int> p1, Optional<Int>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Long>
InitialI::opLong(Optional<Long> p1, Optional<Long>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Float>
InitialI::opFloat(Optional<Float> p1, Optional<Float>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Double>
InitialI::opDouble(Optional<Double> p1, Optional<Double>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<string>
InitialI::opString(Optional<string> p1, Optional<string>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<string>
InitialI::opCustomString(Optional<Util::string_view> p1, Optional<string>& p3, const Current&)
{
    if(p1)
    {
        p3 = p1->to_string();
    }
    return p3;
}

Optional<MyEnum>
InitialI::opMyEnum(Optional<MyEnum> p1, Optional<MyEnum>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<SmallStruct>
InitialI::opSmallStruct(Optional<SmallStruct> p1, Optional<SmallStruct>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<FixedStruct>
InitialI::opFixedStruct(Optional<FixedStruct> p1, Optional<FixedStruct>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<VarStruct>
InitialI::opVarStruct(Optional<VarStruct> p1, Optional<VarStruct>& p3, const Current&)
{
    p3 = p1;
    return p1;
}

Optional<Test::ByteSeq>
InitialI::opByteSeq(Optional<pair<const Ice::Byte*, const Ice::Byte*> > p1, Optional<Test::ByteSeq>& p3,
                    const Current&)
{
    if(p1)
    {
        p3 = Ice::ByteSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::BoolSeq>
InitialI::opBoolSeq(Optional<pair<const bool*, const bool*> > p1, Optional<Test::BoolSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = Ice::BoolSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::ShortSeq>
InitialI::opShortSeq(Optional<pair<const Short*, const Short*> > p1, Optional<Test::ShortSeq>& p3,
                     const Current&)
{
    if(p1)
    {
        p3 = Ice::ShortSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::IntSeq>
InitialI::opIntSeq(Optional<pair<const Int*, const Int*> > p1, Optional<Test::IntSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = Test::IntSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::LongSeq>
InitialI::opLongSeq(Optional<pair<const Long*, const Long*> > p1, Optional<Test::LongSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = Test::LongSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::FloatSeq>
InitialI::opFloatSeq(Optional<pair<const Float*, const Float*> > p1, Optional<Test::FloatSeq>& p3,
                     const Current&)
{
    if(p1)
    {
        p3 = Test::FloatSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<Test::DoubleSeq>
InitialI::opDoubleSeq(Optional<pair<const Double*, const Double*> > p1, Optional<Test::DoubleSeq>& p3,
                      const Current&)
{
    if(p1)
    {
        p3 = Test::DoubleSeq(p1->first, p1->second);
    }
    return p3;
}

Ice::optional<Ice::StringSeq>
InitialI::opStringSeq(Ice::optional<Ice::StringSeq> p1,
                      Ice::optional<Ice::StringSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = p1;
    }
    return p3;
}

Optional<SmallStructSeq>
InitialI::opSmallStructSeq(Optional<pair<const SmallStruct*, const SmallStruct*> > p1,
                           Optional<SmallStructSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = SmallStructSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<SmallStructList>
InitialI::opSmallStructList(Optional<pair<const SmallStruct*, const SmallStruct*> > p1,
                            Optional<SmallStructList>& p3, const Current&)
{
    if(p1)
    {
        p3 = SmallStructList(p1->first, p1->second);
    }
    return p3;
}

Optional<FixedStructSeq>
InitialI::opFixedStructSeq(Optional<pair<const FixedStruct*, const FixedStruct*> > p1,
                           Optional<FixedStructSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = FixedStructSeq(p1->first, p1->second);
    }
    return p3;
}

Optional<FixedStructList>
InitialI::opFixedStructList(Optional<pair<const FixedStruct*, const FixedStruct*> > p1,
                            Optional<FixedStructList>& p3, const Current&)
{
    if(p1)
    {
        p3 = FixedStructList(p1->first, p1->second);
    }
    return p3;
}

Ice::optional<VarStructSeq>
InitialI::opVarStructSeq(Ice::optional<VarStructSeq> p1,
                         Ice::optional<VarStructSeq>& p3, const Current&)
{
    if(p1)
    {
        p3 = p1;
    }
    return p3;
}

Optional<Serializable>
InitialI::opSerializable(Optional<Serializable> p1, Optional<Serializable>& p3, const Current&)
{
    p3 = p1;
    return p3;
}

Optional<IntIntDict>
InitialI::opIntIntDict(Optional<IntIntDict> p1, Optional<IntIntDict>& p3, const Current&)
{
    p3 = p1;
    return p3;
}

Optional<StringIntDict>
InitialI::opStringIntDict(Optional<StringIntDict> p1, Optional<StringIntDict>& p3, const Current&)
{
    p3 = p1;
    return p3;
}

Optional<IntStringDict>
InitialI::opCustomIntStringDict(Optional<std::map<int, Util::string_view> > p1,
                                Optional<IntStringDict>& p3, const Current&)
{
    if(p1)
    {
        p3 = IntStringDict();
        for(std::map<int, Util::string_view>::const_iterator p = p1->begin();
            p != p1->end(); ++p)
        {
            (*p3)[p->first] = p->second.to_string();
        }
    }
    return p3;
}

void
InitialI::opClassAndUnknownOptional(APtr, const Ice::Current&)
{
}

void
InitialI::opVoid(const Ice::Current&)
{
}

InitialI::OpMStruct1MarshaledResult
InitialI::opMStruct1(const Ice::Current& current)
{
    return OpMStruct1MarshaledResult(Test::SmallStruct(), current);
}

InitialI::OpMStruct2MarshaledResult
InitialI::opMStruct2(IceUtil::Optional<Test::SmallStruct> p1, const Ice::Current& current)
{
    return OpMStruct2MarshaledResult(p1, p1, current);
}

InitialI::OpMSeq1MarshaledResult
InitialI::opMSeq1(const Ice::Current& current)
{
    return OpMSeq1MarshaledResult(Test::StringSeq(), current);
}

InitialI::OpMSeq2MarshaledResult
InitialI::opMSeq2(IceUtil::Optional<Test::StringSeq> p1, const Ice::Current& current)
{
    return OpMSeq2MarshaledResult(p1, p1, current);
}

InitialI::OpMDict1MarshaledResult
InitialI::opMDict1(const Ice::Current& current)
{
    return OpMDict1MarshaledResult(Test::StringIntDict(), current);
}

InitialI::OpMDict2MarshaledResult
InitialI::opMDict2(IceUtil::Optional<Test::StringIntDict> p1, const Ice::Current& current)
{
    return OpMDict2MarshaledResult(p1, p1, current);
}

bool
InitialI::supportsRequiredParams(const Ice::Current&)
{
    return false;
}

bool
InitialI::supportsJavaSerializable(const Ice::Current&)
{
    return true;
}

bool
InitialI::supportsCsharpSerializable(const Ice::Current&)
{
    return true;
}

bool
InitialI::supportsCppStringView(const Ice::Current&)
{
    return true;
}

bool
InitialI::supportsNullOptional(const Ice::Current&)
{
    return true;
}
